進入正文以前,想先聊聊輪子(?)
據說輪子出現時,人們都不知道這個東西可作為車輪使用來幫忙搬運重物。
也就是說,當一個新東西出現時,若不知道它的用途也是毫無用武之地,所以在正式學習TypeScipt以前,我想第一天或許可以稍微認識一下TypeScript,了解TypeScript是什麼?知道為何要使用它(解決了什麼問題)?明白何時何地該使用它?
TypeScript is JavaScript with syntax for types.
這是TypeScript官方文件首頁的介紹,一句話解釋了TypeScript的角色和功能 ─ TypeScript其實就是JavaScript的語法再加上型別。
TypeScript是微軟在2012年推出的語法,目的是在解決JavaScript動態型別所衍生的問題。
JavaScript當初是為了添增網頁互動功能所誕生,相較於其他程式語言如C++、Java等,剛開始學習JavaScript可以不用考慮型別或記憶體管理等會打擊信心的複雜問題?對於一位初學者而言比較好上手,也因此JavaScript至今是一個應用愈來愈廣泛、有龐大生態系且發展非常蓬勃的熱門程式語言。
// C++
int x = 20;
// JavaScript
let x = 20;
就像上面舉例的程式碼,C++需要事先明確指定每個變數的型別,然而JavaScript則省去了需要考慮型別、指定型別的小麻煩,但是當要使用JavaScript開發一個龐大的專案時,不用考慮型別這件事可能變成蠻擾人的問題。
這邊舉一個簡單範例,下面寫了一個加總函式,且 x
、y
預期要輸入數字型別(number)的參數。假設今天有個非常雷的隊友不小心輸入字串(string)型別參數 y = "22"
,在JavaScript的語法裡,只要用 +
字符將數字型別的變數值和字串型別的變數值去相加,就會將數字型別變數轉換成字串型別,變成兩個字串串接而得到字串,如下 20
和 "22"
串接變成 "2022"
。
function sum (x, y) {
return x + y;
}
let x = 20;
let y = ”22”;
console.log(sum(x, y)); // “2022”
又或者
let x = 10; // number
…
x = “20”; // 這是可以的!
…
let y = 22
console.log(sum(x, y)); // 又是 “2022”
雖然以上兩個範例看起來是非常簡單容易除錯的範例,不過當今天要開發大型專案並且與多人協作時,就很難保證函式會輸入理想中引數,又或是一不小心犯下將字串賦值給應該是數字型別變數的低級錯誤,這些錯誤可能導致專案出現預期以外的結果(就像上面那些例子一樣!)。
JavaScript是程式執行時期(runtime)才會得知型別的動態型別(dynamic typing)語言,意即寫程式時編輯器或開發工具並不會立刻告知我們輸入值是否為正確型別,甚至還能改變變數的型別,此時若想要避免上述動態型別衍生的問題,TypeScript就能派上用場。
相較於JavaScript是動態型別語言,TypeScript則是靜態型別(static typing)語言,意即它可以在編譯時期(compile time) 檢查程式碼,或者簡單說TypeScript可以在開發當下、不用等到執行程式,就能讓編輯器或開發工具告知開發者型別錯誤,例如:
// TypeScript
let x = 10; // number
…
x = “20”; // error!
在TypeScript語法裡,這個範例的 let x = 10;
也能寫成 let x: number = 10;
明示 x
是一個number型別,但也能像範例一樣讓TypeScript去推導*(infer)* 出這個變數的型別,而賦予型別就是TypeScript的核心概念。
同樣地,從範例可知在寫JavaScript的同時其實也是在寫TypeScript,所以也很常看到有人說:
TypeScript是JavaScript的超集 (Typescript is a superset of JavaScript.)
另外,TypeScript必須先經過TypeScript compiler編譯(或更精確地說轉譯 transpile)成JavaScript語法才能使用,可以嘗試在瀏覽器開發者工具的 console 輸入 let x: number = 10;
就會出現語意錯誤(syntax error)的錯誤訊息,因為瀏覽器的JavaScript引擎根本讀不懂 : number
在這段程式碼的意思。
編譯、轉譯之類的名詞會在第二天有更多說明,總之只要先知道,TypeScript真的只是包裹型別外衣的JavaScript,但是變數有型別了之後還能做什麼?
如同這部短片所說,我們可能會利用裝有許多訊息的物件(object)來傳送與接收資料,有型別的變數就能避免接收到格式不一樣的資料,或預先知道要輸入的資料類型等等,這樣在開發期間就能大大地減少前述所說的錯誤。
這樣看起來TypeScript好像蠻完美的?但實際使用TypeScript也是有一些開發上的缺點。
由於前段只是想介紹TypeScript在程式開發的主要用途,所以寫比較簡單的範例方便說明,但現實生活中可能會需要更複雜的資料。
例如我們設計了一個需要使用者自行輸入資料的程式,假設不作任何防呆機制,不同使用者可能任意輸入了不合格式的資料:
// user1 輸入的資料
let user1 = {
username: “Alice”,
age: 28,
job: “frontend developer”,
salary: 60
};
// user2 輸入的資料
let user2 = {
username: “@$&*1”,
age: 20,
salary: 100,
}
若使用TypeScript語法就能事先規範資料格式去描述資料應該包含哪些內容*(屬性)?內容的型態(型別)*?
// TS
interface User {
username: string,
age: number,
job: “frontend engineer” | “backend engineer” | “fullstack engineer”,
salary: number
}
let user1: User = {
username: “Alice”,
age: 28,
job: “frontend developer”, // error, 只允許輸入 “frontend engineer”
salary: 60
};
let user2: User = {
username: “@$&*1”,
age: 20,
salary: 100,
// error, 沒有包含job屬性
}
到這裡應該看的出來,如果想為程式碼加上這些規範可能會增加一些開發上的時間成本,而且TypeScript語法需要編譯成合法的JavaScript語法才能被瀏覽器讀懂,故也需要花費一些編譯時間。
除此之外,這篇文章也提及,一些非常非常非常小型的專案(或練習?)也許就不會需要TypeScript來徒增學習額外語法和寫更多程式碼的時間;不過相對地,大型專案的除錯時間可能遠遠多於多寫一些規範的時間,此時個人或團隊就其專案狀況權衡時間成本來決定是否使用TypeScript。
寫到這差不多要結束了,就如開頭所說今天這篇文章的目的是先概括性了解TypeScript,從以上內容可以整理幾個關於TypeScript的重要小事(?):
最後,從第1點可以知道,TypeScript並不是為了取代JavaScript而存在,只是為了協助解決JavaScript開發時可能遇到的問題。
此外,TypeScript官方有特別提到,在網路上搜尋程式碼解法可能會看到有些人在詢問「這個問題怎麼用TypeScript寫」,其實看到這類並非在問型別相關的問題時,有可能是在詢問「這個問題怎麼用JavaScript寫」,這時可以試著自動把TypeScript代換成JavaScript就能解決問題了~
參考資料
TypeScript: JavaScript With Syntax For Types.
What is TypeScript?
TypeScript Tutorial
TypeScript Tutorial: A step-by-step guide to learn TypeScript
Learn TypeScript – The Ultimate Beginners Guide
Getting Started With TypeScript